package com.xunk.equipment.service.ruying;

import com.xunk.common.core.exception.CustomException;
import com.xunk.common.core.utils.XunkAssert;
import com.xunk.equipment.domain.EquipmentDO;
import com.xunk.equipment.domain.EquipmentPropertiesData;
import com.xunk.equipment.service.BaseService;
import com.xunk.equipment.service.IAirConditionerService;
import com.xunk.equipment.vo.response.AirConditionerResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xunk.common.core.domain.EquipmentResponse;

import java.util.*;

/**
 * @ProjectName: xunk
 * @Package: com.xunk.equipment.service.ruying
 * @ClassName: AirConditionerService
 * @Author: tangguangyuan
 * @Description: 如影空调service
 * @Date: 2021/3/29 13:51
 * @Version: 1.0
 */
@Service(value = "ruying-air-conditioner")
public class AirConditionerService implements IAirConditionerService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    RuYingControlService ruYingControlService;

    @Autowired
    BaseService baseService;

    private static final String ON_ID = ".2.1";
    private static final String MODE_ID = ".2.2";
    private static final String TEMPERATURE_ID = ".2.3";
    private static final String TARGET_TEMPERATURE_ID = ".2.4";
    private static final String FAN_LEVEL_ID = ".2.5";
    private static final String ALARM_ID = ".2.6";

    //  硬件信息
    private static final String MODEL_ID = ".1.2";
    private static final String SERIAL_NUMBER_ID = ".1.3";
    private static final String FIRMWARE_REVISION_ID = ".1.4";

    @Override
    //获取空调所有属性
    public EquipmentResponse getEquipmentInfo(EquipmentDO equipmentDO) {
        //根据devicesn，deptid获设备影子
        String deviceSn = equipmentDO.getDeviceSn();
        Long deptId = equipmentDO.getDeptId();
        Map<String, String> cacheMap = ruYingControlService.getShadowByDeviceSn(deviceSn, deptId);

        XunkAssert.notEmpty(cacheMap, String.format("设备%s属性不存在", deviceSn));
        AirConditionerResponse response = new AirConditionerResponse();

        Boolean on = Boolean.parseBoolean(cacheMap.getOrDefault(deviceSn.concat(ON_ID), "false"));

        int mode = Integer.parseInt(cacheMap.getOrDefault(deviceSn.concat(MODE_ID), "0"));

        int temperature = Integer.parseInt(cacheMap.getOrDefault(deviceSn.concat(TEMPERATURE_ID), "0"));

        int targetTemperature = Integer.parseInt(cacheMap.getOrDefault(deviceSn.concat(TARGET_TEMPERATURE_ID), "0"));

        int fanLevel = Integer.parseInt(cacheMap.getOrDefault(deviceSn.concat(FAN_LEVEL_ID), "0"));

        int alarm = Integer.parseInt(cacheMap.getOrDefault(deviceSn.concat(ALARM_ID), "0"));

        response.setDeviceSn(deviceSn);
        response.setOn(on);
        response.setMode(mode);
        response.setTemperature(temperature);
        response.setTargetTemperature(targetTemperature);
        response.setFanLevel(fanLevel);
        response.setAlarm(alarm);

        response.setModel(cacheMap.get(deviceSn.concat(MODEL_ID)));
        response.setFirmWare(cacheMap.get(deviceSn.concat(FIRMWARE_REVISION_ID)));
        response.setSerialNumber(cacheMap.get(deviceSn.concat(SERIAL_NUMBER_ID)));

        response.setModeList(modeList);
        response.setTemperatureRange(temperatureRange);
        response.setTargetTemperatureRange(targetTemperatureRange);
        response.setFanLevelList(fanLevelList);
        response.setAlarmList(alarmList);

        response.setSupplier(equipmentDO.getSupplier());

        response.setCandidateModel(baseService.getCandidateModel(equipmentDO.getDeviceBaseId()));
        return response;
    }


    // 空调模式预设值
    public List<Map<String, String>> modeList = new ArrayList<Map<String, String>>(4) {{
        add(createMap("制冷", "3"));
        add(createMap("制热", "4"));
        add(createMap("送风", "7"));
        add(createMap("除湿", "8"));
    }};

    //空调温度预设值
    public Map<String, String> temperatureRange = new HashMap<String, String>(4) {{
        put("min", "0");
        put("max", "100");
        put("step", "1");
    }};

    //空调目标温度预设值
    public Map<String, String> targetTemperatureRange = new HashMap<String, String>(4) {{
        put("min", "19");
        put("max", "30");
        put("step", "1");
    }};

    //风力预设值
    public List<Map<String, String>> fanLevelList = new ArrayList<Map<String, String>>(4) {{
        add(createMap("弱风", "1"));
        add(createMap("中风", "2"));
        add(createMap("强风", "3"));
    }};


    //风力预设值
    public List<Map<String, String>> alarmList = new ArrayList<Map<String, String>>(4) {{
        add(createMap("报警解除", "0"));
        add(createMap("设备报警", "2"));
    }};


    public Map<String, String> createMap(String key, String value) {
        Map<String, String> map = new HashMap<String, String>();
        map.put(key, value);
        return map;
    }


    /**
     * 设置设备单个属性
     * 设置开关外的其他属性时需校验开关状态，开关状态为关闭时无法设置其他属性
     */
    @Override
    public Boolean control(EquipmentDO equipmentDO, String type, String value) {
        List<EquipmentPropertiesData.PropertyData> properties = new ArrayList<>();
        EquipmentPropertiesData equipmentPropertiesData;
        String userId = baseService.findOwnIdByDeptId(equipmentDO.getDeptId());
        String deviceId = equipmentDO.getDeviceSn();
        switch (type) {
            case "on":
                equipmentPropertiesData = setOn(deviceId, Boolean.parseBoolean(value));
                break;
            case "mode":
                this.checkSwitch(equipmentDO);
                equipmentPropertiesData = setModel(deviceId, Integer.parseInt(value));
                break;
            case "targetTemperature":
                this.checkSwitch(equipmentDO);
                equipmentPropertiesData = setTargetTemperature(deviceId, Integer.parseInt(value));
                break;
            case "fanLevel":
                this.checkSwitch(equipmentDO);
                equipmentPropertiesData = setFanLevel(deviceId, Integer.parseInt(value));
                break;
            default:
                throw new CustomException("控制指令非法");
        }


        return Objects.equals(ruYingControlService.setProperties(userId, equipmentPropertiesData), "success");

    }

    //操作空调开关 true-开  false-关
    public EquipmentPropertiesData setOn(String deviceId, Boolean value) {

        String pid = deviceId + ON_ID;

        //测试
        return createEquipmentPropertiesData(pid, value);
    }

    //设置空调模式 3-Cool 4-Heat 7-Fan 8-Dry
    public EquipmentPropertiesData setModel(String deviceId, int value) {

        if (value != 3 && value != 4 && value != 7 && value != 8)
            logger.error("空调模式非法!");
        String pid = deviceId + MODE_ID;
        return createEquipmentPropertiesData(pid, value);
    }

    //设置空调目标温度
    public EquipmentPropertiesData setTargetTemperature(String deviceId, int value) {
        if (value < 19 || value > 30) {
            logger.error("空调目标温度非法!");
        }
        String pid = deviceId + TARGET_TEMPERATURE_ID;
        return createEquipmentPropertiesData(pid, value);
    }

    //设置空调风力
    public EquipmentPropertiesData setFanLevel(String deviceId, int value) {
        if (value != 1 && value != 2 && value != 3)
            logger.error("空调风力非法");
        String pid = deviceId + FAN_LEVEL_ID;
        return createEquipmentPropertiesData(pid, value);
    }

    /**
     * 判断开关状态返回结果
     */
    public void checkSwitch(EquipmentDO equipmentDO) {
        AirConditionerResponse response = (AirConditionerResponse) this.getEquipmentInfo(equipmentDO);
        if (!Objects.isNull(response.getOn()) && !response.getOn())
            throw new CustomException("空调未开启！");
    }

    /**
     * 创建EquipmentPropertiesData
     */
    public EquipmentPropertiesData createEquipmentPropertiesData(String pid, Object value) {
        EquipmentPropertiesData equipmentPropertiesData = new EquipmentPropertiesData();
        List<EquipmentPropertiesData.PropertyData> propertyData = new ArrayList<EquipmentPropertiesData.PropertyData>(1) {{
            add(new EquipmentPropertiesData.PropertyData(pid, value));
        }};
        equipmentPropertiesData.setProperties(propertyData);
        //测试
        return equipmentPropertiesData;

    }
}

